Mix c & ASM¶
簡介¶
為了加快效能與特殊需求可以使用,組合語言與c語言混和撰寫方式
os:linux(x64)(#e)
編譯器:gcc
接下來皆以64位元linux示範
與32位元會有所不一樣
Linux system call¶
System call implement location¶
以下舉例:__x64_sys_write
-
從syscall_64.tbl尋找__x64_sys_write
根據該檔案知道 __x64_sys_write 編號1 所以暫存器%rax 填入1
-
搜尋實做的函數
1
SYSCALL_DEFINEx(function_name,....){...}
function_name:write
x:這個編號不一定
__x64_sys_write
__x64_sys_write實做位置 我們看到ksys_write(fd, buf, count)有三個變數 根據ABI規則依序填入暫存器 fd %rdi buf %rsi count %rdx
1 2 3 4 | SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,size_t, count) { return ksys_write(fd, buf, count); } |
根據上面答案建立此表格
表格1-1
%rax | System call | %rdi | %rsi | %rdx | %r10 | %r8 | %r9 |
---|---|---|---|---|---|---|---|
1 | __x64_sys_write | fd | buf | count |
參考資源:
C/C++ function definitions without assembly
How can I find the implementations of Linux kernel system calls?
輸出範例¶
C內嵌ASM¶
實做直接呼叫linux system code
根據1-1表格找到的資訊
關於此段指令為什麼填入1的理由
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | void print_asm(char *arg1,long int size){ __asm__ ( "mov $1, %%rax\n"//system call 編碼 "mov $1, %%rdi\n"//fd 設定1 代表把字串輸入/dev/stdout 這裡就是螢幕輸出地方 "mov %0,%%rsi\n"//輸入字串記憶體位置 "mov %1, %%rdx\n" //這裡輸入字串長度 ,可以跟記憶體位置搭配來輸出到螢幕 "syscall"//x64 要用此呼叫systemcall 不能在使用int $0x80 : :"m" (arg1),"m" (size) //詳細請參考gcc inline asm ); } int main(void) { char *d="ss\n"; print_asm(d,3); return 0; } |